package ca.uwindsor.cs.deepweb.estimation.method.border;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class Matrix {
	protected HashMap<Integer, Integer> docid_inverseDocumentWeight;
	protected int[][] term_docslist;
	protected float[] queryWeight;
	private int index;
	private int p;
	private int numofterms;

	/**
	 * The corrected matrix
	 * 
	 * @param numofterms
	 *            The number of terms that will be submitted
	 */
	public Matrix(int numofterms) {
		this.numofterms = numofterms;
		term_docslist = new int[numofterms][];
		docid_inverseDocumentWeight = new HashMap<Integer, Integer>(
				numofterms * 100);
		queryWeight = new float[numofterms];
	}

	/**
	 * add a query with the documents it can capture
	 * 
	 * @param i
	 *            the index of a term
	 * @param documents
	 *            the list of documents that added term can capture
	 * @return the document indexes
	 */
	public int[] addQuery(int i, List<String> documents) {
		int[] array = null;
		if (documents.size() != 0) {
			array = new int[documents.size()];
			index = 0;
			// add new documents to unique id list
			for (String s : documents) {
				p = s.hashCode();
				// if (!docid_inverseDocumentWeight.containsKey(hashcode)) {
				// docid_index.put(hashcode, p);
				// } else {
				// p = docid_index.get(hashcode).intValue();
				// }
				array[index] = p;
				index++;
			}
		}
		// add to term-docs list
		term_docslist[i] = array;
		return array;
	}

	/**
	 * To check if a document has a weight calculated
	 * 
	 * @param docid
	 *            the id of a document
	 * @return true if it already has its weight;
	 */
	public boolean hasDocument(Integer docid) {
		return docid_inverseDocumentWeight.containsKey(docid);
	}

	/**
	 * Set the number of queries a document can capture
	 * 
	 * @param docindex
	 *            the index of a document
	 * @param inverseweight
	 *            the number of queries it can capture
	 */
	public void setInverseDocumentWeight(int docindex, int inverseweight) {
		docid_inverseDocumentWeight.put(new Integer(docindex), new Integer(
				inverseweight));
	}

	/**
	 * Calculate the weight of a query
	 */
	public void calculateQueryWeight() {
		int[] l;
		float weight;
		for (index = 0; index < numofterms; index++) {
			l = term_docslist[index];
			weight = 0;
			if (l != null) {
				for (int i : l) {
					if (docid_inverseDocumentWeight.get(i) != null) {
						weight += 1 / docid_inverseDocumentWeight.get(i)
								.floatValue();
					}
				}
			}
			queryWeight[index] = weight;
		}
	}

	/**
	 * Get the inverse weight of documents. It is the reciprocal number of
	 * queries a document can capture
	 * 
	 * @return the documentWeight
	 */
	// public ArrayList<Integer> getInverseDocumentWeight() {
	// return inverseDocumentWeight;
	// }
	/**
	 * @return the mean weight of queries
	 */
	public float getMeanQueryWeight() {
		float mean = 0;
		float sum = 0;
		for (float f : queryWeight) {
			sum += f;
		}
		mean = sum / queryWeight.length;
		return mean;
	}
	
	/**
	 * @return the array of weights
	 */
	public float[] getWeightofQueries(){
		return this.queryWeight;
	}
	
	/**
	 * @return return the ids set of unique document downloaded
	 */
	public Set<Integer> getUniqueDocumentIDs(){
		return docid_inverseDocumentWeight.keySet();
	}
}
